package org.atlantis.grosbeak.json;

import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

import org.atlantis.grosbeak.lang.Exceptions;
import org.atlantis.grosbeak.lang.stream.StringReader;
import org.atlantis.grosbeak.lang.stream.StringWriter;

/**
 * JSON转换工具包。
 * 
 * @author <a href="mailto:seenoevil.cn@gmail.com">SeeNoEvil</a>
 * 
 */
public class Jsons {

	/**
	 * 从一个文本输入流中读取JSON信息，并将其转换成一个对象。对象的类型是根据JSON的信息来确定的。
	 * 
	 * @param reader
	 *            包含JSON信息的输入流。
	 * @return Java对象。
	 * @throws JsonException
	 */
	public static Object fromJson(Reader reader) throws JsonException {
		return new JsonAnalyzer(reader).parseFromJson(null, null);
	}

	/**
	 * 从文本输入流中读取JSON信息，并将其转换成一个指定类型（通过type参数指定）的对象。
	 * 
	 * @param type
	 *            生成对象的类型。
	 * @param reader
	 *            包含JSON信息的输入流。
	 * @return Java对象。
	 * @throws JsonException
	 */
	public static <T> T fromJson(Class<T> type, Reader reader)
			throws JsonException {
		return new JsonAnalyzer(reader).parseFromJson(type, null);
	}

	/**
	 * 将JSON格式格式的字符串，转换成相应的对象。
	 * 
	 * @param cs
	 *            JSON格式的字符串。
	 * @see #fromJson(Reader)
	 * @return 转换成的对象。
	 * @throws JsonException
	 */
	public static Object fromJson(CharSequence cs) throws JsonException {
		return fromJson(new StringReader(cs));
	}

	/**
	 * 将JSON格式的字符串，转换成指定类型的对象。
	 * 
	 * @param type
	 *            指定的类型。
	 * @param cs
	 *            JSON格式的字符串。
	 * @see #fromJson(Class, Reader)
	 * @return 具有指定类型的对象。
	 * @throws JsonException
	 */
	public static <T> T fromJson(Class<T> type, CharSequence cs)
			throws JsonException {
		return fromJson(type, new StringReader(cs));
	}

	/**
	 * 把一个Java对象转换成JSON格式的字符串返回。并采用format方式对JSON字符串进行格式化。
	 * 
	 * @param obj
	 *            需要转换成JSON字符串的对象。
	 * @return JSON字符串。
	 * @see org.atlantis.grosbeak.json.JsonHandler#format()
	 */
	public static String toJson(Object obj) {
		return toJson(obj, null);
	}

	/**
	 * 把一个Java对象转换成JSON格式的字符串返回。可以指定JSON字符串的格式化输出。
	 * 
	 * @param obj
	 *            需要转换成JSON字符串的对象。
	 * @param handler
	 *            JSON字符串格式化的样式。
	 * @return JSON字符串。
	 * @see org.atlantis.grosbeak.json.JsonHandler#compress()
	 * @see org.atlantis.grosbeak.json.JsonHandler#full()
	 * @see org.atlantis.grosbeak.json.JsonHandler#format()
	 */
	public static String toJson(Object obj, JsonHandler handler) {
		StringBuilder sb = new StringBuilder();
		toJson(new StringWriter(sb), obj, handler);
		return sb.toString();
	}

	/**
	 * 把一个Java对象转换成JSON格式的字符串，并把该字符串写入到一个文本输出流中。并采用format方式对JSON字符串进行格式化。
	 * 
	 * @param writer
	 *            文本输出流。
	 * @param obj
	 *            需要转换成JSON字符串的对象。
	 * @see org.atlantis.grosbeak.json.JsonHandler#format()
	 */
	public static void toJson(Writer writer, Object obj) {
		toJson(writer, obj, null);
	}

	/**
	 * 把一个Java对象转换成JSON格式的字符串，并把该字符串写入到一个文本输出流中。可以指定JSON字符串的格式化输出。
	 * 
	 * @param writer
	 *            文本输出流。
	 * @param obj
	 *            需要转换成JSON字符串的对象。
	 * @param handler
	 *            JSON字符串格式化的样式。
	 * @see org.atlantis.grosbeak.json.JsonHandler#compress()
	 * @see org.atlantis.grosbeak.json.JsonHandler#full()
	 * @see org.atlantis.grosbeak.json.JsonHandler#format()
	 */
	public static void toJson(Writer writer, Object obj, JsonHandler handler) {
		if (handler == null)
			handler = JsonHandler.format();
		try {
			new JsonRender(writer, handler).rendering(obj);
			writer.flush();
		} catch (IOException e) {
			throw Exceptions.makeThrow(JsonException.class, e, "");
		}
	}
}
